package com.qiaofang.applet.service.property.service.impl;

import com.google.common.collect.Lists;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.constants.PropertyRedundanceFieldEnum;
import com.qiaofang.applet.service.member.domain.Department;
import com.qiaofang.applet.service.member.domain.Employee;
import com.qiaofang.applet.service.member.service.DepartmentService;
import com.qiaofang.applet.service.other.domain.CityCompany;
import com.qiaofang.applet.service.property.domain.*;
import com.qiaofang.applet.service.property.service.PropertyDataHandleService;
import com.qiaofang.applet.service.property.service.PropertyRedundancyService;
import com.qiaofang.applet.service.property.service.dto.PropertyRedundanceFieldDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author: youqing.yang
 * @create: 2020/09/28 09:28
 **/
@Service("propertyRedundancyService")
@Slf4j
public class PropertyRedundancyServiceImpl extends MongoBaseService<Property, String> implements PropertyRedundancyService {

    public PropertyRedundancyServiceImpl(MongoRepository<Property, String> repository) {
        super(repository);
    }

    protected int pageSize = 100;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private PropertyDataHandleService propertyDataHandleService;

    @Autowired
    private DepartmentService departmentService;

    @Override
    public void UpdateOtherToProperty(CityCompany cityCompany) {
        // TODO: 2020/9/28  
    }

    @Override
    public void UpdatePropertyToOther(CityCompany cityCompany) {
        try {
            Query query = new Query();
            Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
            criteria.and("relationUpdate").is(false);
            query.addCriteria(criteria);

            //房源变动数据
            List<Property> properties = mongoTemplate.find(query, Property.class);
            Long startTime = System.currentTimeMillis();

            //循环请求
            List<List<Property>> partition = Lists.partition(properties, pageSize);
            partition.forEach(list->{
                propertyDataHandleService.initAllPropertyRedundanceField(list);
            });

            Long endTime = System.currentTimeMillis();
            log.info("run companyUuid {} UpdatePropertyToOther end {} ", cityCompany.getCompanyUuid(), (endTime - startTime));
            Update updateDepartment = new Update();
            //更新内容
            updateDepartment.set("relationUpdate", true);
            mongoTemplate.updateMulti(query, updateDepartment, "property_property");
        } catch (Exception e) {
            log.error("UpdatePropertyToOther error{}", e);
        }
    }

    /**
     * 楼盘冗余
     * @param cityCompany
     */
    @Override
    public void redundancyEstate(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyEstate start ",cityCompany.getCompanyUuid());
        Long startTime=System.currentTimeMillis();
        int limit = 100;
        long offset = 0;
        List<Estate> estates = mongoTemplate.find(query.limit(limit).skip(offset), Estate.class);
        while (!CollectionUtils.isEmpty(estates)) {
            List<PropertyRedundanceFieldDto> estateDtos = Optional.ofNullable(estates).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.ESTATE);
                        dto.setFieldUuid(item.getEstateUniqueUuid());
                        dto.setFieldValue(item.getEstateName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(estateDtos);
            // re-query list
            estates = mongoTemplate.find(query.skip(offset+=limit), Estate.class);
        }
        Long endTime=System.currentTimeMillis();
        log.info("run companyUuid {} redundancyEstate end {} ",cityCompany.getCompanyUuid(),(endTime-startTime));
        //修改关联更新状态
        Update updateEstate = new Update();
        //更新内容
        updateEstate.set("relationUpdate", true);
        mongoTemplate.updateMulti(query,updateEstate,"property_estate");
    }

    /**
     * VR冗余
     * @param cityCompany
     */
    @Override
    public void redundancyVr(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyVr start ",cityCompany.getCompanyUuid());
        Long startTime=System.currentTimeMillis();
        //分页查询
        int limit = 100;
        long offset = 0;
        List<PropertyVr> propertyVrs = mongoTemplate.find(query.limit(limit).skip(offset), PropertyVr.class);
        while (!CollectionUtils.isEmpty(propertyVrs)) {
            List<PropertyRedundanceFieldDto> vrDtos = Optional.ofNullable(propertyVrs).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.VR);
                        dto.setFieldUuid(item.getPropertyUuid());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(vrDtos);
            // re-query list
            propertyVrs = mongoTemplate.find(query.skip(offset += limit), PropertyVr.class);
        }

        Long endTime=System.currentTimeMillis();
        log.info("run companyUuid {} redundancyVr end {} ",cityCompany.getCompanyUuid(),(endTime-startTime));
        //修改关联更新状态
        Update updateVr = new Update();
        //更新内容
        updateVr.set("relationUpdate", true);
        mongoTemplate.updateMulti(query,updateVr,"property_property_vr");
    }

    /**
     * 视频冗余
     * @param cityCompany
     */
    @Override
    public void redundancyVideo(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyVideo start ", cityCompany.getCompanyUuid());
        Long startTime = System.currentTimeMillis();
        //分页查询
        int limit = 100;
        long offset = 0;
        List<PropertyVideo> propertyVideos = mongoTemplate.find(query.limit(limit).skip(offset), PropertyVideo.class);
        while (!CollectionUtils.isEmpty(propertyVideos)) {
            List<PropertyRedundanceFieldDto> videoDtos = Optional.ofNullable(propertyVideos).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.VIDEO);
                        dto.setFieldUuid(item.getPropertyUuid());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(videoDtos);
            // re-query list
            propertyVideos = mongoTemplate.find(query.skip(offset += limit), PropertyVideo.class);
        }
        Long endTime = System.currentTimeMillis();
        log.info("run companyUuid {} redundancyVideo end {} ", cityCompany.getCompanyUuid(), (endTime - startTime));
        Update updateDistrictsDtos = new Update();
        //更新内容
        updateDistrictsDtos.set("relationUpdate", true);
        mongoTemplate.updateMulti(query, updateDistrictsDtos, "property_property_video");
    }

    /**
     * 商圈冗余
     * @param cityCompany
     */
    @Override
    public void redundancyArea(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyArea start ",cityCompany.getCompanyUuid());
        Long startTime=System.currentTimeMillis();
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Area> areas = mongoTemplate.find(query.limit(limit).skip(offset), Area.class);
        while (!CollectionUtils.isEmpty(areas)) {
            List<PropertyRedundanceFieldDto> areaDtos = Optional.ofNullable(areas).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.AREA);
                        dto.setFieldUuid(item.getAreaUuid());
                        dto.setFieldValue(item.getAreaName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(areaDtos);
            // re-query list
            areas = mongoTemplate.find(query.skip(offset += limit), Area.class);
        }
        Long endTime=System.currentTimeMillis();
        log.info("run companyUuid {} redundancyArea end {} ",cityCompany.getCompanyUuid(),(endTime-startTime));
        //修改关联更新状态
        Update updateArea = new Update();
        //更新内容
        updateArea.set("relationUpdate", true);
        mongoTemplate.updateMulti(query,updateArea,"property_area");
    }

    /**
     * 区域冗余
     * @param cityCompany
     */
    @Override
    public void redundancyDistrict(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyDistrict start ", cityCompany.getCompanyUuid());
        Long startTime = System.currentTimeMillis();
        //分页查询
        int limit = 100;
        long offset = 0;
        List<District> districts = mongoTemplate.find(query.limit(limit).skip(offset), District.class);
        while (!CollectionUtils.isEmpty(districts)) {
            List<PropertyRedundanceFieldDto> districtsDtos = Optional.ofNullable(districts).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.DISTRICT);
                        dto.setFieldUuid(item.getDistrictUuid());
                        dto.setFieldValue(item.getDistrictName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(districtsDtos);
            // re-query list
            districts = mongoTemplate.find(query.skip(offset += limit), District.class);
        }
        Long endTime = System.currentTimeMillis();
        log.info("run companyUuid {} redundancyDistrict end {} ", cityCompany.getCompanyUuid(), (endTime - startTime));
        Update updateDistricts = new Update();
        //更新内容
        updateDistricts.set("relationUpdate", true);
        mongoTemplate.updateMulti(query, updateDistricts, "property_district");
    }

    /**
     * 业主联系号码冗余
     * @param cityCompany
     */
    @Override
    public void redundancyContact(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyContact start ", cityCompany.getCompanyUuid());
        Long startTime = System.currentTimeMillis();
        //分页查询
        int limit = 100;
        long offset = 0;
        List<PropertyContact> propertyContacts = mongoTemplate.find(query.limit(limit).skip(offset), PropertyContact.class);
        while (!CollectionUtils.isEmpty(propertyContacts)) {
            List<PropertyRedundanceFieldDto> contactDtos = Optional.ofNullable(propertyContacts).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.CONTACT);
                        dto.setFieldUuid(item.getPropertyUuid());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(contactDtos);
            // re-query list
            propertyContacts = mongoTemplate.find(query.skip(offset += limit), PropertyContact.class);
        }
        Long endTime = System.currentTimeMillis();
        log.info("run companyUuid {} redundancyContact end {} ", cityCompany.getCompanyUuid(), (endTime - startTime));
        Update updateContact = new Update();
        //更新内容
        updateContact.set("relationUpdate", true);
        mongoTemplate.updateMulti(query, updateContact, "property_property_contact");

    }

    /**
     * 经纪人信息冗余
     * @param cityCompany
     */
    @Override
    public void redundancyEmployee(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyEmployee start ", cityCompany.getCompanyUuid());
        Long startTime = System.currentTimeMillis();

        try {
            redundancyEmployeeOne(query, cityCompany);
            redundancyEmployeeTwo(query, cityCompany);
            redundancyEmployeeThree(query, cityCompany);
        } catch (Exception e) {
            log.error("redundancyEmployee error {} companyUuid {}", e, cityCompany.getCompanyCity());
        }


        Long endTime = System.currentTimeMillis();
        log.info("run companyUuid {} redundancyEmployee end {} ", cityCompany.getCompanyUuid(), (endTime - startTime));
        Update updateEmployee = new Update();
        //更新内容
        updateEmployee.set("relationUpdate", true);
        mongoTemplate.updateMulti(query, updateEmployee, "member_employee");
    }

    public void redundancyEmployeeOne(Query query,CityCompany cityCompany){
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Employee> employees1 = mongoTemplate.find(query.limit(limit).skip(offset), Employee.class);
        while (!CollectionUtils.isEmpty(employees1)) {
            List<PropertyRedundanceFieldDto> Emoloyee1Dtos = Optional.ofNullable(employees1).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.EMPLOYEE1);
                        dto.setFieldUuid(item.getEmployeeUuid());
                        dto.setFieldValue(item.getEmployeeName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(Emoloyee1Dtos);
            // re-query list
            employees1 = mongoTemplate.find(query.skip(offset += limit), Employee.class);
        }
    }

    public void redundancyEmployeeTwo(Query query,CityCompany cityCompany){
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Employee> employees2 = mongoTemplate.find(query.limit(limit).skip(offset), Employee.class);
        while (!CollectionUtils.isEmpty(employees2)) {
            List<PropertyRedundanceFieldDto> Emoloyee2Dtos = Optional.ofNullable(employees2).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.EMPLOYEE2);
                        dto.setFieldUuid(item.getEmployeeUuid());
                        dto.setFieldValue(item.getEmployeeName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(Emoloyee2Dtos);
            // re-query list
            employees2 = mongoTemplate.find(query.skip(offset += limit), Employee.class);
        }
    }

    public void redundancyEmployeeThree(Query query,CityCompany cityCompany){
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Employee> employees3 = mongoTemplate.find(query.limit(limit).skip(offset), Employee.class);
        while (!CollectionUtils.isEmpty(employees3)) {
            List<PropertyRedundanceFieldDto> Emoloyee3Dtos = Optional.ofNullable(employees3).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.EMPLOYEE3);
                        dto.setFieldUuid(item.getEmployeeUuid());
                        dto.setFieldValue(item.getEmployeeName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(Emoloyee3Dtos);
            // re-query list
            employees3 = mongoTemplate.find(query.skip(offset += limit), Employee.class);
        }
    }

    /**
     * 部门冗余
     * @param cityCompany
     */
    @Override
    public void redundancyDepartment(CityCompany cityCompany){
        if (cityCompany==null){
            return;
        }
        Query query = new Query();
        Criteria criteria = Criteria.where("companyUuid").is(cityCompany.getCompanyUuid());
        criteria.and("relationUpdate").is(false);
        query.addCriteria(criteria);
        log.info("run companyUuid {} redundancyDepartment start ", cityCompany.getCompanyUuid());
        Long startTime = System.currentTimeMillis();

        try {
            redundancyDepartmentOne(query, cityCompany);
            redundancyDepartmentTwo(query, cityCompany);
            redundancyDepartmentThree(query, cityCompany);
        } catch (Exception e) {
            log.error("redundancyDepartment error {} companyUuid {}", e, cityCompany.getCompanyCity());
        }

        Long endTime = System.currentTimeMillis();
        log.info("run companyUuid {} redundancyDepartment end {} ", cityCompany.getCompanyUuid(), (endTime - startTime));
        Update updateDepartment = new Update();
        //更新内容
        updateDepartment.set("relationUpdate", true);
        mongoTemplate.updateMulti(query, updateDepartment, "member_department");
    }

    public void redundancyDepartmentOne(Query query, CityCompany cityCompany) {
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Department> departments = mongoTemplate.find(query.limit(limit).skip(offset), Department.class);
        while (!CollectionUtils.isEmpty(departments)) {
            List<PropertyRedundanceFieldDto> department1Dtos = Optional.ofNullable(departments).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.DEPT1);
                        dto.setFieldUuid(item.getDeptUuid());
                        dto.setFieldValue(item.getDeptName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(department1Dtos);
            // re-query list
            departments = mongoTemplate.find(query.skip(offset += limit), Department.class);
        }
    }

    public void redundancyDepartmentTwo(Query query, CityCompany cityCompany) {
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Department> departments = mongoTemplate.find(query.limit(limit).skip(offset), Department.class);
        while (!CollectionUtils.isEmpty(departments)) {
            List<PropertyRedundanceFieldDto> department2Dtos = Optional.ofNullable(departments).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.DEPT2);
                        dto.setFieldUuid(item.getDeptUuid());
                        dto.setFieldValue(item.getDeptName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(department2Dtos);
            // re-query list
            departments = mongoTemplate.find(query.skip(offset += limit), Department.class);
        }
    }

    public void redundancyDepartmentThree(Query query, CityCompany cityCompany) {
        //分页查询
        int limit = 100;
        long offset = 0;
        List<Department> departments = mongoTemplate.find(query.limit(limit).skip(offset), Department.class);
        while (!CollectionUtils.isEmpty(departments)) {
            List<PropertyRedundanceFieldDto> department3Dtos = Optional.ofNullable(departments).orElseGet(Lists::newArrayList)
                    .stream().map(item -> {
                        PropertyRedundanceFieldDto dto = new PropertyRedundanceFieldDto();
                        dto.setCompanyUuid(cityCompany.getCompanyUuid());
                        dto.setPropertyRedundanceField(PropertyRedundanceFieldEnum.DEPT3);
                        dto.setFieldUuid(item.getDeptUuid());
                        dto.setFieldValue(item.getDeptName());
                        return dto;
                    }).collect(Collectors.toList());
            propertyDataHandleService.updatePropertyRedundanceField(department3Dtos);
            // re-query list
            departments = mongoTemplate.find(query.skip(offset += limit), Department.class);
        }
    }
}
